home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / ed3_1_1 / part03 < prev    next >
Encoding:
Internet Message Format  |  1991-11-07  |  47.7 KB

  1. Path: news.larc.nasa.gov!amiga-request
  2. From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v91i174: ED3 1.1 - a primitive 3D editor for use with NU3, Part03/06
  4. Reply-To: rodent@netcom.com (Ben Discoe)
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga.v91i174@ab20.larc.nasa.gov>
  7. References: <comp.sources.amiga.v91i172@ab20.larc.nasa.gov>
  8. Date: 07 Nov 91 15:54:25 GMT
  9. Approved: tadguy@uunet.UU.NET (Tad Guy)
  10. X-Mail-Submissions-To: amiga@uunet.uu.net
  11. X-Post-Discussions-To: comp.sys.amiga.misc
  12.  
  13. Submitted-by: rodent@netcom.com (Ben Discoe)
  14. Posting-number: Volume 91, Issue 174
  15. Archive-name: utilities/ed3-1.1/part03
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 3 (of 6)."
  24. # Contents:  edio.c freq.c
  25. # Wrapped by tadguy@ab20 on Thu Nov  7 10:53:52 1991
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'edio.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'edio.c'\"
  29. else
  30. echo shar: Extracting \"'edio.c'\" \(24785 characters\)
  31. sed "s/^X//" >'edio.c' <<'END_OF_FILE'
  32. X/*
  33. X    These are functions of ed3 that do keyboard, mouse and file IO.
  34. X
  35. X10-22-91 chg YZ to ZY
  36. X10-21-91 fix to allow saving defaults!
  37. X10-20-91 fix to refresh after loading!
  38. X10-13-91 add tell_user_overflow() and tell_user_changes(), get_undo_bufsize()
  39. X         add load_defaults() and save_defaults()
  40. X09-09-91 made handle_key() portable
  41. X09-04-91 chg load_data to call add_point, add_face
  42. X09-06-91 adapted to use coord instead of short
  43. X*/
  44. X
  45. X#include "sysnogr.h"
  46. X
  47. X/* Menu numbers */
  48. X#define ME_PROJECT        0
  49. X#define ME_EDIT            1
  50. X#define ME_POLYHEDRA    2
  51. X#define ME_SPECIAL        3
  52. X#define ME_OPTIONS        4
  53. X
  54. X/* Menu items numbers */
  55. X#define MI_LOAD            0
  56. X#define MI_SAVE            1
  57. X#define MI_CLEAR        2
  58. X/* --- 3 */
  59. X#define MI_SAVE_DEF        4    /* save defaults */
  60. X#define MI_ABOUT        5
  61. X/* --- 6 */
  62. X#define MI_QUIT            7
  63. X
  64. X#define MI_CUT            0
  65. X#define MI_COPY            1
  66. X#define MI_PASTE        2
  67. X#define MI_DUPLICATE    3
  68. X#define MI_ERASE        4
  69. X#define MI_SELECTALL    6
  70. X#define MI_SELECTCON    7
  71. X#define MI_DESELECTALL    8
  72. X#define MI_POINTSONLY    10
  73. X#define MI_FACESONLY    11
  74. X#define MI_EXCLUSIVE    12
  75. X
  76. X#define MI_TETRA        0
  77. X#define MI_OCTA            1
  78. X#define MI_CUBE            2
  79. X#define MI_ICOSA        3
  80. X#define MI_DODEC        4
  81. X#define MI_DODEC_RHOMB    5
  82. X#define MI_CUBOCTA        6
  83. X/* --- 7 */
  84. X#define MI_GLOBE        8
  85. X#define MI_SURF_REV        9
  86. X
  87. X#define MI_RESET_ZOOM    0
  88. X#define MI_FREQUENCY    1
  89. X#define MI_CONNECT        2
  90. X#define MI_DUAL            3
  91. X#define MI_UNFOLD        4
  92. X#define MI_NORMALIZE    5
  93. X#define MI_STELLATE        6
  94. X#define MI_ORIGIN        7
  95. X#define MI_SETCLOCK        8
  96. X
  97. Xchar *errstring[ERRORS] =
  98. X{
  99. X  "Everything is Okay",
  100. X  "There was nothing it that file",
  101. X  "Can't open file",
  102. X  "That's not the kind of file ED3 can read",
  103. X  "Not enough memory",
  104. X  "Not enough memory for points",
  105. X  "Not enough memory for faces",
  106. X  "Not enough memory for polygons",
  107. X  "Bad face: face refers to non-existent point"
  108. X};
  109. X
  110. X
  111. Xvoid handle_gadget(id)
  112. Xint id;
  113. X{
  114. X  switch (id)
  115. X  {
  116. X    case GID_ADD:        mode = M_ADDP; break;
  117. X    case GID_DELETE:    mode = M_DELP; break;
  118. X    case GID_SELECTOR:    mode = M_SELE; break;
  119. X    case GID_MOVE:        mode = M_MOVP; break;
  120. X    case GID_FACE:        mode = M_FACE; break;    /* new face */
  121. X    case GID_POLY:        mode = M_POLY; break;    /* new polygon */
  122. X    case GID_MORE:        break;
  123. X    case GID_DEFACE:     mode = M_DEFA; deselect_all(); break;
  124. X    case GID_DEPOLY:     mode = M_DEPO; deselect_all(); break;
  125. X    case GID_MORE2:        break;
  126. X    case GID_ROTATE:    mode = M_ROTA; break;
  127. X    case GID_ROTP:        break;
  128. X    case GID_ZOOM:        mode = M_ZOOM; break;
  129. X    case GID_DIST:
  130. X        mode = M_DIST;
  131. X        if (!flags.display_dtool)
  132. X        {
  133. X            flags.display_dtool = 1;
  134. X            toggle_menuitem(ME_OPTIONS, MI_DISTANCETOOL);
  135. X            draw_distance_tool();
  136. X        }
  137. X        break;
  138. X    case GID_GLUE:        mode = M_GLUE; break;
  139. X    case GID_UNDO:        undo(); break;
  140. X    case GID_REDO:        redo(); break;
  141. X    case GID_XY:        dmode = DM_XY; gz = 0; break;
  142. X    case GID_XZ:        dmode = DM_XZ; gy = 0; break;
  143. X    case GID_ZY:        dmode = DM_ZY; gx = 0; break;
  144. X    case GID_3D:        break;
  145. X    case GID_color1:    colors.newface = 1; break;
  146. X    case GID_color2:    colors.newface = 2; break;
  147. X    case GID_color3:    colors.newface = 3; break;
  148. X  }
  149. X  switch (id)
  150. X  {
  151. X    case GID_XY:
  152. X    case GID_XZ:
  153. X    case GID_ZY:
  154. X        convert_points();
  155. X        refresh_all();
  156. X  }
  157. X  draw_bars();
  158. X}
  159. X
  160. X
  161. Xvoid mouse_down(buttons)    /* what to do when a mouse button is pressed */
  162. Xchar buttons;                /* 0 = first, 1 = second, 2 = double click with first */
  163. X{
  164. X    index nearest;    /* closest point to the cursor */
  165. X
  166. X    convert_to_xyz(mx, my);
  167. X
  168. X    switch(mode)    /* many mode need to operate on the selected point */
  169. X    {
  170. X        case M_DELP:
  171. X        case M_SELE:
  172. X        case M_DEFA:
  173. X        case M_DEPO:
  174. X        case M_FACE:
  175. X        case M_POLY:
  176. X        case M_MOVP:
  177. X        case M_MORE:
  178. X        case M_KMORE:
  179. X        case M_DIST:
  180. X        case M_GLUE:
  181. X            if (buttons & 1)    /* second button */
  182. X                nearest = find_nearest_in_space(gx, gy, gz, -1);
  183. X            else
  184. X                nearest = find_nearest_on_screen(mx, my, -1);
  185. X    }
  186. X    switch(mode)
  187. X    {
  188. X        case M_ADDP:
  189. X            begin_operation();
  190. X            draw_point(add_point(gx, gy, gz), colors.point);
  191. X            end_operation();
  192. X            break;
  193. X        case M_DELP:
  194. X            begin_operation();
  195. X            del_point(nearest, 0, 0);
  196. X            end_operation();
  197. X            break;
  198. X        case M_SELE:
  199. X            toggle_select(buttons, nearest);
  200. X            break;
  201. X        case M_MOVP:
  202. X            start_moving_point(buttons, nearest);
  203. X            break;
  204. X        case M_FACE: start_face(nearest); break;
  205. X        case M_POLY: start_poly(nearest); break;
  206. X        case M_MORE: add_segment(nearest); break;
  207. X
  208. X        case M_DEFA: start_to_kill_face(nearest); break;
  209. X        case M_DEPO: start_to_kill_poly(nearest); break;
  210. X        case M_KMORE: kill_segment(nearest); break;
  211. X
  212. X        case M_ROTA: set_rot_axis(gx, gy, gz); break;
  213. X        case M_ROTP: rotate(); break;
  214. X        case M_ZOOM: zoom(buttons); break;
  215. X        case M_DIST: distance_tool(buttons, nearest); break;
  216. X        case M_GLUE: glue(nearest); break;
  217. X    }
  218. X    show_counts();
  219. X}
  220. X
  221. X
  222. Xvoid mouse_up()            /* what to do when the first button goes up */
  223. X{
  224. X    if (flags.moving_points) finish_move();
  225. X    if (flags.drag_dtool)
  226. X    {
  227. X#if 0
  228. X        draw_distance_tool();
  229. X#endif
  230. X        flags.drag_dtool = 0;
  231. X    }
  232. X    show_counts();
  233. X}
  234. X
  235. X
  236. Xvoid update_movement(newx, newy)
  237. Xcoord newx, newy;
  238. X{
  239. X  mx = newx;
  240. X  my = newy;
  241. X
  242. X  if (flags.in_edit_area)
  243. X  {
  244. X    /* have we moved out? */
  245. X    if (mx <= edit_minx || my <= edit_miny)
  246. X    {
  247. X      flags.in_edit_area = 0;
  248. X      enable_menus(TRUE);
  249. X    }
  250. X  }
  251. X  else
  252. X  {
  253. X    /* have we moved in? */
  254. X    if (mx > edit_minx && my > edit_miny)
  255. X    {
  256. X      flags.in_edit_area = 1;
  257. X      enable_menus(FALSE);
  258. X    }
  259. X  }
  260. X
  261. X  if (!flags.in_edit_area) return;
  262. X
  263. X  /* erase stuff */
  264. X  if (flags.crosshair) draw_hair();    /* Erase/Redraw crosshair */
  265. X  if (flags.drag_dtool)
  266. X    draw_distance_tool();    /* Erase/Redraw distance tool */
  267. X  if (flags.moving_points)    /* If we are dragging some points */
  268. X    toggle_dragged_points();    /* then erase them */
  269. X
  270. X  /* allow the pointer to move */
  271. X  convert_to_xyz(mx, my);
  272. X  if (flags.show_coords) draw_coords(0);
  273. X
  274. X  /* redraw stuff */
  275. X  if (flags.moving_points)    /* If we are dragging some points */
  276. X    toggle_dragged_points();    /* then redraw them */
  277. X  if (flags.drag_dtool)
  278. X  {
  279. X    dtool_end[flags.which_end].x = gx;
  280. X    dtool_end[flags.which_end].y = gy;
  281. X    dtool_end[flags.which_end].z = gz;
  282. X    draw_distance_tool();    /* Erase/Redraw distance tool */
  283. X  }
  284. X  if (flags.crosshair) draw_hair();            /* Erase/Redraw crosshair */
  285. X  if (mode == M_ROTP)
  286. X  {
  287. X    draw_rot();                /* Erase angle */
  288. X    convert_to_xy(axis.x, axis.y, axis.z);
  289. X    rot_angle = atan2((double)(py-my), (double)(mx-px));
  290. X    draw_rot();    /* Redraw angle */
  291. X  }
  292. X}
  293. X
  294. X
  295. Xvoid handle_key(key)
  296. Xshort key;
  297. X{
  298. X    /* first, keys that work in all modes */
  299. X
  300. X    switch(key)
  301. X    {
  302. X        case 27:    /* Esc */
  303. X          if (!selected)
  304. X            select_all();
  305. X          else
  306. X            deselect_all();
  307. X          break;
  308. X        case 'c':
  309. X            flags.crosshair ^= 1;
  310. X            toggle_menuitem(ME_OPTIONS, MI_CROSSHAIR);
  311. X            draw_hair();
  312. X            break;
  313. X        case 'd':
  314. X            toggle_menuitem(ME_OPTIONS, MI_DISTANCETOOL);
  315. X            toggle_dtool();
  316. X            break;
  317. X        case 'm':
  318. X            mode = M_MOVP;
  319. X            deselect_all();
  320. X            break;
  321. X        case 'u': undo(); break;
  322. X        case 'r': redo(); break;
  323. X        case 8:
  324. X            del_selected();
  325. X            show_counts();    /* it's likely we've changed something */
  326. X            break;
  327. X        case 'x': flags.debug ^= 1; break;
  328. X        case '8':
  329. X            if (dmode == DM_XY) gz++;
  330. X            if (dmode == DM_XZ) gy++;
  331. X            if (dmode == DM_ZY) gx++;
  332. X            if (flags.show_coords) draw_coords(0); break;
  333. X        case '2':
  334. X            if (dmode == DM_XY) gz--;
  335. X            if (dmode == DM_XZ) gy--;
  336. X            if (dmode == DM_ZY) gx--;
  337. X            if (flags.show_coords) draw_coords(0); break;
  338. X        case 'a': zoom(1); break;
  339. X        case 'z': zoom(0); break;
  340. X        case ' ':
  341. X            convert_points();
  342. X            refresh_all();
  343. X            break;
  344. X    }
  345. X}
  346. X
  347. X
  348. Xvoid handle_menu(menunum, itemnum, flags)
  349. Xint menunum, itemnum, flags;
  350. X{
  351. X    switch (menunum)
  352. X    {
  353. X      case ME_PROJECT:
  354. X        handle_project(itemnum); break;
  355. X      case ME_EDIT:
  356. X        handle_edit(itemnum, flags); break;
  357. X      case ME_POLYHEDRA:
  358. X        handle_polyhedra(itemnum); break;
  359. X      case ME_SPECIAL:
  360. X        handle_special(itemnum); break;
  361. X      case ME_OPTIONS:
  362. X        handle_options(itemnum, flags); break;
  363. X    }
  364. X    show_counts();    /* in case we've altered the number of points or faces */
  365. X}
  366. X
  367. X
  368. Xvoid handle_project(itemnum)
  369. Xint itemnum;
  370. X{
  371. X    switch (itemnum)
  372. X    {
  373. X        case MI_LOAD:      load_request(); refresh_all(); break;
  374. X        case MI_SAVE:      save_request(); break;
  375. X        case MI_CLEAR:      new(); break;
  376. X        case MI_SAVE_DEF: save_defaults(); break;
  377. X        case MI_ABOUT:      about_help(); break;
  378. X        case MI_QUIT:
  379. X            if (changes)
  380. X            {
  381. X                if (!tell_user_changes()) break;
  382. X            }
  383. X            sys_exit("");
  384. X            break;
  385. X    }
  386. X}
  387. X
  388. X
  389. Xvoid handle_edit(itemnum, mflags)
  390. Xint itemnum;
  391. X{
  392. X  int value = mflags;
  393. X
  394. X  switch (itemnum)
  395. X  {
  396. X    case MI_CUT: break;
  397. X    case MI_COPY: break;
  398. X    case MI_PASTE: break;
  399. X    case MI_DUPLICATE: duplicate(!flags.points_only); break;
  400. X    case MI_ERASE: del_selected(); break;
  401. X    case MI_SELECTALL: select_all(); break;
  402. X    case MI_SELECTCON: select_connected(-1); break;
  403. X    case MI_DESELECTALL: deselect_all(); break;
  404. X    case MI_POINTSONLY:    flags.points_only = value; break;
  405. X    case MI_FACESONLY:    flags.faces_only = value; break;
  406. X    case MI_EXCLUSIVE:    flags.exclusive_del = value; break;
  407. X  }
  408. X}
  409. X
  410. X
  411. Xvoid handle_polyhedra(itemnum)
  412. Xint itemnum;
  413. X{
  414. X  switch(itemnum)
  415. X  {
  416. X    case MI_GLOBE:
  417. X      create_globe();
  418. X      refresh_all();
  419. X      break;
  420. X    case 7:
  421. X      break;
  422. X    default:
  423. X      create_poly(itemnum);
  424. X      refresh_all();
  425. X      break;
  426. X  }
  427. X}
  428. X
  429. X
  430. Xvoid handle_special(itemnum)
  431. Xint itemnum;
  432. X{
  433. X  char refresh = 0;
  434. X
  435. X  switch (itemnum)
  436. X  {
  437. X    case MI_RESET_ZOOM:
  438. X        reset_zoom();
  439. X        convert_points();
  440. X        refresh = 1;
  441. X        break;
  442. X    case MI_FREQUENCY:    frequency(); refresh = 1; break;
  443. X    case MI_CONNECT:    break;
  444. X    case MI_DUAL:        find_dual(); refresh = 1; break;
  445. X    case MI_UNFOLD:        unfold(); break;
  446. X    case MI_NORMALIZE:    normalize(); refresh = 1; break;
  447. X    case MI_STELLATE:    stellate(); refresh = 1; break;
  448. X    case MI_ORIGIN:     center_to_origin(); refresh = 1; break;
  449. X    case MI_SETCLOCK:    set_clockwisdom(); break;
  450. X  }
  451. X  if (refresh) refresh_all();
  452. X}
  453. X
  454. X
  455. Xvoid handle_options(itemnum, mflags)
  456. Xint itemnum;
  457. XUSHORT mflags;
  458. X{
  459. X  int value = mflags;
  460. X
  461. X  switch (itemnum)
  462. X  {
  463. X    case MI_ASSUME_POLY:
  464. X        flags.assume_poly = value;
  465. X        break;
  466. X    case MI_COORDS:
  467. X        flags.show_coords = value;
  468. X        draw_coords(!value);    /* if value is 0, erase */
  469. X        break;
  470. X    case MI_CROSSHAIR:
  471. X        flags.crosshair = value;
  472. X        draw_hair();
  473. X        break;
  474. X    case MI_DISTANCETOOL:
  475. X        toggle_dtool();
  476. X        break;
  477. X    case MI_ROTATEALL:
  478. X        flags.rotate_all = value;
  479. X        break;
  480. X    case MI_UNDOBUF:
  481. X        flags.undo_active = value;
  482. X        init_undo();
  483. X        break;
  484. X    case MI_UNDOBUFSIZE:
  485. X        get_undo_bufsize();
  486. X        break;
  487. X  }
  488. X}
  489. X
  490. X
  491. Xvoid add_all_menus()
  492. X{
  493. X  add_menu("Project");
  494. X  add_menu("Edit");
  495. X  add_menu("Polyhedra");
  496. X  add_menu("Special");
  497. X  add_menu("Options");
  498. X
  499. X  add_menu_item(0, "Load   ", 0, 'O');
  500. X  add_menu_item(0, "Save   ", 0, 'S');
  501. X  add_menu_item(0, "Clear       ", 0, 0);
  502. X  add_menu_item(0, "----", MO_NOTENABLED, 0);
  503. X  add_menu_item(0, "Save defaults", 0, 0);
  504. X  add_menu_item(0, "About/Help   ", 0, 0);
  505. X  add_menu_item(0, "----", MO_NOTENABLED, 0);
  506. X  add_menu_item(0, "Quit   ", 0, 'Q');
  507. X
  508. X  add_menu_item(1, "Cut           ", MO_NOTENABLED, 'X');
  509. X  add_menu_item(1, "Copy          ", MO_NOTENABLED, 'C');
  510. X  add_menu_item(1, "Paste         ", MO_NOTENABLED, 'V');
  511. X  add_menu_item(1, "Duplicate     ", 0, 'D');
  512. X  add_menu_item(1, "Erase    (Backspace)", 0, 0);
  513. X  add_menu_item(1, "----------    ", MO_NOTENABLED, 0);
  514. X  add_menu_item(1, "Select All (Esc Esc)", 0, 0);
  515. X  add_menu_item(1, "Select Connected    ", 0, 0);
  516. X  add_menu_item(1, "Deselect All   (Esc)", 0, 0);
  517. X  add_menu_item(1, "----------    ", MO_NOTENABLED, 0);
  518. X  add_menu_item(1, "Points Only?     ", MO_TOGGLE, 0);
  519. X  add_menu_item(1, "Faces/Polys Only?", MO_TOGGLE, 0);
  520. X  add_menu_item(1, "Exclusive Delete?", MO_TOGGLE | MO_CHECKED, 0);
  521. X
  522. X  add_menu_item(2, "Tetrahedron  ", 0, 0);
  523. X  add_menu_item(2, "Octahedron   ", 0, 0);
  524. X  add_menu_item(2, "Cube         ", 0, 0);
  525. X  add_menu_item(2, "Icosahedron  ", 0, 0);
  526. X  add_menu_item(2, "Dodecahedron ", 0, 0);
  527. X  add_menu_item(2, " (rhombic)   ", 0, 0);
  528. X  add_menu_item(2, "Cuboctahedron", 0, 0);
  529. X  add_menu_item(2, "-------------", MO_NOTENABLED, 0);
  530. X  add_menu_item(2, "Globe        ", 0, 0);
  531. X  add_menu_item(2, "Surf. of Rev.", MO_NOTENABLED, 0);
  532. X
  533. X  add_menu_item(3, "Reset Zoom ", 0, 'R');
  534. X  add_menu_item(3, "Frequency  ", 0, 'F');
  535. X  add_menu_item(3, "Connect 'em      ", MO_NOTENABLED, 0);
  536. X  add_menu_item(3, "Find Dual  ", 0, 'D');
  537. X  add_menu_item(3, "Unfold           ", MO_NOTENABLED, 0);
  538. X  add_menu_item(3, "Normalize  ", 0, 'N');
  539. X  add_menu_item(3, "Stellate         ", 0, 0);
  540. X  add_menu_item(3, "Center -> Origin ", 0, 0);
  541. X  add_menu_item(3, "Set Clockwisdom  ", 0, 0);
  542. X
  543. X  add_menu_item(4, "Assume Polyhedron?    ", MO_TOGGLE | (flags.assume_poly  ? MO_CHECKED : 0), 0);
  544. X  add_menu_item(4, "Display Coords?       ", MO_TOGGLE | (flags.show_coords  ? MO_CHECKED : 0), 0);
  545. X  add_menu_item(4, "Display Crosshair? (c)", MO_TOGGLE | (flags.crosshair    ? MO_CHECKED : 0), 0);
  546. X  add_menu_item(4, "Distance Tool?     (d)", MO_TOGGLE | (flags.display_dtool? MO_CHECKED : 0), 0);
  547. X  add_menu_item(4, "Rotate Everything?    ", MO_TOGGLE | (flags.rotate_all   ? MO_CHECKED : 0), 0);
  548. X  add_menu_item(4, "Undo Buffer Active?   ", MO_TOGGLE | (flags.undo_active  ? MO_CHECKED : 0), 0);
  549. X  add_menu_item(4, "Set Undo Buffer Size  ", 0, 0);
  550. X
  551. X  sys_attach_menus();
  552. X}
  553. X
  554. X
  555. Xvoid add_all_gadgets()
  556. X{
  557. X  add_gadget("ADD", 0);
  558. X  add_gadget("DELETE", 0);
  559. X  add_gadget("SELECTOR", 0);
  560. X  add_gadget("MOVE", 0);
  561. X  add_gadget("FACE", 0);
  562. X  add_gadget("POLY", 0);
  563. X  add_gadget(" (more)", GF_NOSELECT);
  564. X  add_gadget("DEFACE", 0);
  565. X  add_gadget("DEPOLY", 0);
  566. X  add_gadget(" (more)", GF_NOSELECT);
  567. X  add_gadget("ROTATE", 0);
  568. X  add_gadget("(rotate)", GF_NOSELECT);
  569. X  add_gadget("ZOOM", 0);
  570. X  add_gadget("DISTANCE", 0);
  571. X  add_gadget("GLUE", 0);
  572. X  add_gadget("UNDO", 0);
  573. X  add_gadget("REDO", 0);
  574. X  add_gadget("XY front", 0);
  575. X  add_gadget("XZ top", 0);
  576. X  add_gadget("ZY side ", 0);
  577. X  add_gadget("> 3D <", GF_NOSELECT);
  578. X  add_gadget("color1", 0);
  579. X  add_gadget("color2", 0);
  580. X  add_gadget("color3", 0);
  581. X
  582. X  sys_refresh_gadgets();
  583. X}
  584. X
  585. X
  586. Xsave_data(fname)
  587. Xchar *fname;
  588. X{
  589. X    uindex i, j;
  590. X    FILE *fp;
  591. X
  592. X    if (!points) return ERR_NOTHING;
  593. X    fp = fopen(fname, "w");
  594. X    if (!fp) return ERR_CANTOPEN;
  595. X
  596. X    fprintf(fp, "#simple 3D file\n");
  597. X    fprintf(fp, "points %d\n", points);
  598. X    fprintf(fp, "faces %d\n", faces);
  599. X    fprintf(fp, "polys %d\n", polys);
  600. X
  601. X    /* save points */
  602. X    fprintf(fp, "\n# points are stored as \"point X Y Z\"\n\n");
  603. X    for (i = 0; i < points; i++)
  604. X#if INTEGER
  605. X        fprintf(fp, "point %d %d %d\n", point[i].x, point[i].y, point[i].z);
  606. X#else
  607. X        fprintf(fp, "point %lf %lf %lf\n", point[i].x, point[i].y, point[i].z);
  608. X#endif
  609. X
  610. X    /* save faces */
  611. X    if (faces)
  612. X    {
  613. X        fprintf(fp, "\n# faces are stored as \"face p0 p1 p2 color\"\n\n");
  614. X        for (i = 0; i < faces; i++)
  615. X            fprintf(fp, "face %d %d %d %d\n",
  616. X                face[i].p[0], face[i].p[1], face[i].p[2], face[i].color);
  617. X    }
  618. X
  619. X    /* save polygons */
  620. X    if (polys)
  621. X    {
  622. X        fprintf(fp, "\n# polygons are stored as \"poly N p1 ... pN color\"\n\n");
  623. X        for (i = 0; i < polys; i++)
  624. X        {
  625. X            fprintf(fp, "poly %d ", poly[i].verts);
  626. X            for (j = 0; j < poly[i].verts; j++)
  627. X                fprintf(fp, "%d ", poly[i].p[j]);
  628. X            fprintf(fp, "%d\n", poly[i].color);
  629. X        }
  630. X    }
  631. X    fprintf(fp, "\n");
  632. X    fclose(fp);
  633. X  return OKAY;
  634. X}
  635. X
  636. X
  637. Xload_data(fname)
  638. Xchar *fname;
  639. X{
  640. X    FILE *fp;
  641. X    int j, k[MAX_EDGES];
  642. X    coord x_lo, y_lo, z_lo,
  643. X         x_hi, y_hi, z_hi,
  644. X         x_size, y_size, z_size,
  645. X         greatest;
  646. X    char buf[128];        /* maximum line length */
  647. X    uindex i;
  648. X#if INTEGER
  649. X    int x, y, z;
  650. X#else
  651. X    double x, y, z;
  652. X#endif
  653. X
  654. X  if (!(fp = fopen(fname, "r")))
  655. X    return ERR_CANTOPEN;
  656. X
  657. X  fgets(buf, 85, fp);    /* Read first line */
  658. X  if (strncmp(buf, "#simple 3D file", 15))
  659. X    return ERR_NOTED3;
  660. X
  661. X    for (i = 0; i < 3; i++)
  662. X    {
  663. X        fgets(buf, 85, fp);
  664. X        if (*buf == 0) break;
  665. X        if (!strncmp(buf, "points ", 7))
  666. X        {
  667. X            sscanf(buf, "points %d\n", &j);
  668. X
  669. X            /* see if this value is OK */
  670. X            if (!j)
  671. X            {
  672. X                fclose(fp);
  673. X                return ERR_NOTHING;
  674. X            }
  675. X            if (j >= MAX_POINTS)
  676. X            {
  677. X                if (more_points(j + 100))
  678. X                {
  679. X                    printf("unable to make room for %d points.\n", j);
  680. X                    fclose(fp);
  681. X                    return ERR_NOMEM_POINT;
  682. X                }
  683. X            }
  684. X        }
  685. X        if (!strncmp(buf, "faces ", 7))
  686. X        {
  687. X            fscanf(fp, "faces %d\n", &j);
  688. X            if (j >= MAX_FACES)
  689. X            {
  690. X                if (more_faces(j + 100))
  691. X                {
  692. X                    fclose(fp);
  693. X                    return ERR_NOMEM_FACE;
  694. X                }
  695. X            }
  696. X        }
  697. X        if (!strncmp(buf, "polys ", 7))
  698. X        {
  699. X            fscanf(fp, "polys %d\n", &j);
  700. X            if (j >= MAX_POLYS)
  701. X            {
  702. X                if (more_polys(j + 100))
  703. X                {
  704. X                    fclose(fp);
  705. X                    return ERR_NOMEM_POLY;
  706. X                }
  707. X            }
  708. X        }
  709. X    }
  710. X
  711. X    /* in case the object is much larger or smaller than the screen, we need
  712. X        to adjust our scaling based on the bounding box of the data */
  713. X    x_lo = y_lo = z_lo = x_hi = y_hi = z_hi = 0;
  714. X    faces = points = polys = 0;
  715. X
  716. X    while (fgets(buf, 85, fp) != NULL)
  717. X    {
  718. X        if (!strncmp(buf, "face ", 5))
  719. X        {
  720. X            sscanf(buf + 5, "%d %d %d %d", &k[0], &k[1], &k[2], &k[3]);
  721. X            if (k[0] >= points || k[1] >= points || k[2] >= points)
  722. X            {
  723. X                fclose(fp);
  724. X                return ERR_BADFACE;
  725. X            }
  726. X            add_face0(k[0], k[1], k[2], k[3]);
  727. X        }
  728. X        else if (!strncmp(buf, "poly ", 5))
  729. X        {
  730. X            sscanf(buf + 5, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
  731. X                k+0, k+1, k+2, k+3, k+4, k+5, k+6, k+7, k+8, k+9,
  732. X                k+10, k+11, k+12, k+13, k+14, k+15, k+16, k+17, k+18, k+19, k+20);
  733. X            allocate_poly(k[0], k[k[0]+1]);
  734. X            for (i = 0; i < k[0]; i++)
  735. X                poly[polys].p[i] = k[i+1];
  736. X            finish_poly(1);
  737. X        }
  738. X        else if (!strncmp(buf, "point ", 6))
  739. X        {
  740. X#if INTEGER
  741. X            sscanf(buf + 6, "%d %d %d", &x, &y, &z);
  742. X#else
  743. X            sscanf(buf + 6, "%lf %lf %lf", &x, &y, &z);
  744. X#endif
  745. X            if (x < x_lo) x_lo = x;
  746. X            if (x > x_hi) x_hi = x;
  747. X            if (y < y_lo) y_lo = y;
  748. X            if (y > y_hi) y_hi = y;
  749. X            if (z < z_lo) z_lo = z;
  750. X            if (z > z_hi) z_hi = z;
  751. X            add_point0(x, y, z);
  752. X        }
  753. X        else if (*buf && *buf != '#' && *buf != '\n')
  754. X        {
  755. X            printf("Don't understand line: %s", buf);
  756. X        }
  757. X    }
  758. X
  759. X    x_size = max(-x_lo, x_hi);    /* since coordinates are always centered */
  760. X    y_size = max(-y_lo, y_hi);
  761. X    z_size = max(-z_lo, z_hi);
  762. X     greatest = max(x_size, y_size);
  763. X    greatest = max(greatest, z_size);
  764. X
  765. X    /* scale = units per pixel.  Here, "greatest" is the most units
  766. X        that half the screen must accomodate */
  767. X    SCALE = (double)greatest / (double)(symax >> 1) * 1.1;
  768. X
  769. X    fclose(fp);
  770. X    convert_points();
  771. X    return OKAY;
  772. X}
  773. X
  774. X
  775. Xvoid get_undo_bufsize()
  776. X{
  777. X    long new_ab = act_buf;
  778. X    long new_ob = op_buf;
  779. X    int go = 1, ok = 1, event;
  780. X    int id;
  781. X    long data;
  782. X
  783. X    sys_window(34, 4, "Set Undo Buffer Size");
  784. X    sys_movecur(7,0);
  785. X    sys_say_text("Size in bytes:");
  786. X    sys_get_long(new_ab, 1);
  787. X    sys_movecur(1,1);
  788. X    sys_say_text("Maximum undo levels:");
  789. X    sys_get_long(new_ob, 2);
  790. X    sys_movecur(7,2);
  791. X    sys_boolean(" OK ", 3);
  792. X    sys_movecur(17,2);
  793. X    sys_boolean("Cancel", 4);
  794. X    sys_activate(1);
  795. X
  796. X    while (go)
  797. X    {
  798. X        event = sys_read_event(&id, &data);
  799. X        switch (event)
  800. X        {
  801. X        case EV_CANCEL:
  802. X            go = 0;
  803. X            break;
  804. X        case EV_CHECKINT:
  805. X/*            printf("checkint gadget %d, data %ld\n", id, data);    */
  806. X        case EV_HITRETURN:
  807. X/*            if (event == EV_HITRETURN) printf("hit return on gadget %d, data %ld\n", id, data); */
  808. X            if (id == 1)
  809. X            {
  810. X                if (data > 32000) data = 32000;
  811. X                if (data < 1000) data = 1000;
  812. X                new_ab = data;
  813. X                if (event == EV_HITRETURN) sys_activate(2);
  814. X            }
  815. X            if (id == 2)
  816. X            {
  817. X                if (data > 2000) data = 2000;
  818. X                if (data < 10) data = 10;
  819. X                new_ob = data;
  820. X                if (event == EV_HITRETURN) { go = 0; ok = 1; }
  821. X            }
  822. X            break;
  823. X        case EV_HITBUTTON:
  824. X/*            printf("hit button on gadget %d, data %ld\n", id, data); */
  825. X            if (id == 3) { go = 0; ok = 1; }
  826. X            else { go = 0; ok = 0; }
  827. X            break;
  828. X        }
  829. X    }
  830. X    if (ok)
  831. X    {
  832. X        act_buf = new_ab;
  833. X        op_buf = new_ob;
  834. X    }
  835. X    sys_close_window();
  836. X}
  837. X
  838. X
  839. X/* Tell the user that the requested operation will overflow the undo buffer. */
  840. X/* Returns TRUE if the user decides to turn off undo and proceed anyway. */
  841. X
  842. Xint tell_user_overflow()
  843. X{
  844. X    int id, event;
  845. X    long data;
  846. X
  847. X    sys_window(45, 6, "Warning!");
  848. X    sys_movecur(0,0);
  849. X    sys_say_text("The operation you requested will overflow");
  850. X    sys_movecur(0,1);
  851. X    sys_say_text("the undo buffer.  Do you wish to turn undo");
  852. X    sys_movecur(0,2);
  853. X    sys_say_text("off and proceed, or cancel the operation?");
  854. X    sys_movecur(1,4);
  855. X    sys_boolean("Turn off and proceed", 1);
  856. X    sys_say_text("  ");
  857. X    sys_boolean("Cancel operation", 2);
  858. X
  859. X    while (1)
  860. X    {
  861. X        event = sys_read_event(&id, &data);
  862. X        switch (event)
  863. X        {
  864. X            case EV_HITBUTTON:
  865. X                if (id == 1)
  866. X                {
  867. X                    flags.undo_active = 0;
  868. X                    toggle_menuitem(ME_OPTIONS, MI_UNDOBUF);
  869. X                    init_undo();
  870. X                    sys_close_window();
  871. X                    return 1;
  872. X                }
  873. X            case EV_CANCEL:
  874. X                sys_close_window();
  875. X                return 0;    /* cancel operation */
  876. X                break;
  877. X        }
  878. X    }
  879. X}
  880. X
  881. X
  882. X/* Warn the user that there are unsaved changed */
  883. X/* returns TRUE if the user say its OK to continue */
  884. X
  885. Xint tell_user_changes()
  886. X{
  887. X    char buf[20];
  888. X    int go = 1, ok = 1, event;
  889. X    int id;
  890. X    long data;
  891. X
  892. X    sys_window(37, 5, "Warning: Unsaved Changes!");
  893. X    sys_movecur(1,0);
  894. X    sys_say_text("You have made");
  895. X    sprintf(buf, " %d ", changes);
  896. X    sys_say_text(buf);
  897. X    sys_say_text("unsaved ");
  898. X    sys_say_text((changes < -1 || changes > 1) ? "changes." : "change.");
  899. X    sys_movecur(1,1);
  900. X    sys_say_text((changes < -1 || changes > 1) ? "They" : "It");
  901. X    sys_say_text(" will be lost if you continue!");
  902. X
  903. X    sys_movecur(4,3);
  904. X    sys_boolean("OK - continue", 1);
  905. X    sys_movecur(20,3);
  906. X    sys_boolean("Cancel!", 2);
  907. X
  908. X    while (go)
  909. X    {
  910. X        event = sys_read_event(&id, &data);
  911. X        switch (event)
  912. X        {
  913. X        case EV_HITBUTTON:
  914. X            if (id == 1) { go = 0; ok = 1; break; }
  915. X        case EV_CANCEL:
  916. X            go = 0;
  917. X            ok = 0;
  918. X            break;
  919. X        }
  920. X    }
  921. X    sys_close_window();
  922. X    return (ok);
  923. X}
  924. X
  925. X
  926. X/* Tell the user about ed3, and provide a little help. */
  927. X
  928. Xvoid about_help()
  929. X{
  930. X    int go = 1, ok = 1, event;
  931. X    int id;
  932. X    long data;
  933. X
  934. X    sys_window(59, 13, "About ED3 - and some Help");
  935. X    sys_movecur(0,0);
  936. X    sys_say_text("ED3 is a 3D object editor placed in the public domain by");
  937. X    sys_movecur(0,1);
  938. X    sys_say_text("its author, Ben Discoe.  That means I didn't copyright it");
  939. X    sys_movecur(0,2);
  940. X    sys_say_text("and neither can you.  Information should be free, y'all.");
  941. X    sys_movecur(0,3);
  942. X#if INTEGER
  943. X    sys_say_text("This is the integer version.  A floating-point version");
  944. X#else
  945. X    sys_say_text("This is the floating-point version.  An integer version");
  946. X#endif
  947. X    sys_movecur(0,4);
  948. X    sys_say_text("is also available.  The source is freely available.");
  949. X    sys_movecur(0,5);
  950. X    sys_say_text("\"Faces\" refer to triangles, and \"Polys\" refer to");
  951. X    sys_movecur(0,6);
  952. X    sys_say_text("polygons with more than 3 sides.  This distinction is made");
  953. X    sys_movecur(0,7);
  954. X    sys_say_text("for reasons of efficiency.  Undo/Redo is available and is");
  955. X    sys_movecur(0,8);
  956. X    sys_say_text("limited only by the amount of memory you give it.");
  957. X    sys_movecur(0,9);
  958. X    sys_say_text("To learn the special features, experiment!");
  959. X
  960. X    sys_movecur(12,11);
  961. X    sys_boolean(" OK ", 1);
  962. X    sys_movecur(28,11);
  963. X    sys_boolean("Keyboard Shortcuts", 2);
  964. X
  965. X    while (go)
  966. X    {
  967. X        event = sys_read_event(&id, &data);
  968. X        switch (event)
  969. X        {
  970. X        case EV_HITBUTTON:
  971. X            if (id == 2) { go = 0; ok = 0; break; }
  972. X        case EV_CANCEL:
  973. X            go = 0;
  974. X            ok = 1;
  975. X            break;
  976. X        }
  977. X    }
  978. X    sys_close_window();
  979. X    if (ok) return;
  980. X
  981. X    sys_window(57, 6, "Keyboard Shortcuts");
  982. X    sys_movecur(0,0);
  983. X    sys_say_text(" c - toggle crosshair        Esc - deselect/select All");
  984. X    sys_movecur(0,1);
  985. X    sys_say_text(" d - toggle distance-tool      a - zoom in");
  986. X    sys_movecur(0,2);
  987. X    sys_say_text(" m - Move mode                 z - zoom out");
  988. X    sys_movecur(0,3);
  989. X    sys_say_text(" u - undo              backspace - kill selected");
  990. X    sys_movecur(0,4);
  991. X    sys_say_text(" r - redo              space bar - full refresh");
  992. X    sys_movecur(22,5);
  993. X    sys_boolean(" OK ", 1);
  994. X
  995. X    go = 1;
  996. X    while (go)
  997. X    {
  998. X        event = sys_read_event(&id, &data);
  999. X        switch (event)
  1000. X        {
  1001. X        case EV_HITBUTTON:
  1002. X        case EV_CANCEL:
  1003. X            go = 0;
  1004. X            break;
  1005. X        }
  1006. X    }
  1007. X    sys_close_window();
  1008. X}
  1009. X
  1010. X
  1011. Xvoid save_request()
  1012. X{
  1013. X  char *fname;
  1014. X  int status;
  1015. X
  1016. X  fname = sys_file_requestor("Save 3D file", "*.3d");
  1017. X  if (! *fname) return;
  1018. X
  1019. X  if (status = save_data(fname))
  1020. X    SimpleRequest("Problem saving: %s.", errstring[status]);
  1021. X}
  1022. X
  1023. X
  1024. Xvoid load_request()
  1025. X{
  1026. X  char *fname;
  1027. X  int status;
  1028. X
  1029. X  fname = sys_file_requestor("Load 3D file", "*.3d");
  1030. X  if (! *fname) return;
  1031. X
  1032. X  if (status = load_data(fname))
  1033. X    SimpleRequest("Problem loading: %s.", errstring[status]);
  1034. X}
  1035. X
  1036. X
  1037. Xsave_defaults()
  1038. X{
  1039. X    FILE *fp;
  1040. X
  1041. X    fp = fopen("ed3-defs", "w");
  1042. X    if (!fp) return ERR_CANTOPEN;
  1043. X
  1044. X    fprintf(fp, "%d ", flags.assume_poly);
  1045. X    fprintf(fp, "%d ", flags.display_dtool);
  1046. X    fprintf(fp, "%d ", flags.show_coords);
  1047. X    fprintf(fp, "%d ", flags.crosshair);
  1048. X    fprintf(fp, "%d ", flags.rotate_all);
  1049. X    fprintf(fp, "%d ", flags.undo_active);
  1050. X    fprintf(fp, "%d ", act_buf);
  1051. X    fprintf(fp, "%d ", op_buf);
  1052. X
  1053. X    fclose(fp);
  1054. X    return OKAY;
  1055. X}
  1056. X
  1057. X
  1058. Xload_defaults()
  1059. X{
  1060. X    FILE *fp;
  1061. X    int i1, i2, i3, i4;
  1062. X
  1063. X    fp = fopen("ed3-defs", "r");
  1064. X    if (!fp) return ERR_CANTOPEN;
  1065. X
  1066. X    /* we must scanf indirectly because the destination variables may
  1067. X        not be ints */
  1068. X
  1069. X    fscanf(fp, "%d ", &i1);
  1070. X    fscanf(fp, "%d ", &i2);
  1071. X    fscanf(fp, "%d ", &i3);
  1072. X    fscanf(fp, "%d ", &i4);
  1073. X
  1074. X    flags.assume_poly = i1;
  1075. X    flags.display_dtool = i2;
  1076. X    flags.show_coords = i3;
  1077. X    flags.crosshair = i4;
  1078. X
  1079. X    fscanf(fp, "%d ", &i1);
  1080. X    fscanf(fp, "%d ", &i2);
  1081. X    fscanf(fp, "%d ", &i3);
  1082. X    fscanf(fp, "%d ", &i4);
  1083. X
  1084. X    flags.rotate_all = i1;
  1085. X    flags.undo_active = i2;
  1086. X    act_buf = i3;
  1087. X    op_buf = i4;
  1088. X
  1089. X    fclose(fp);
  1090. X    return OKAY;
  1091. X}
  1092. X
  1093. X
  1094. END_OF_FILE
  1095. if test 24785 -ne `wc -c <'edio.c'`; then
  1096.     echo shar: \"'edio.c'\" unpacked with wrong size!
  1097. fi
  1098. # end of 'edio.c'
  1099. fi
  1100. if test -f 'freq.c' -a "${1}" != "-c" ; then 
  1101.   echo shar: Will not clobber existing file \"'freq.c'\"
  1102. else
  1103. echo shar: Extracting \"'freq.c'\" \(19873 characters\)
  1104. sed "s/^X//" >'freq.c' <<'END_OF_FILE'
  1105. X/*
  1106. X    This module of of ed3 devoted to raising polyhedra to
  1107. X    higher frequencies.
  1108. X
  1109. X10-13-91 frequency() now checks to see if there is room in the undo buf
  1110. X09-19-91 found tiny bug (missing a -1) on line 385.  It caused glitches.
  1111. X08-26-91 fixed small (final?) bug in freq algo
  1112. X08-24-91 attempt to extend algorithm to quadrilaterals.
  1113. X        We could try to do this by doubling the complexity of the
  1114. X        current code (same size, double complex) or by doubling
  1115. X        the size.  Having a second type of shape (quads) could mean
  1116. X        4 times the complexity (n^2 effect!).
  1117. X*/
  1118. X
  1119. X#include "sysnogr.h"
  1120. X
  1121. X
  1122. X/*   freq = 1       freq = 2       freq = 3   etc.
  1123. X        A              A              A
  1124. X       / \            / \            / \
  1125. X      /   \          /   \          0---1
  1126. X     /     \ ->     0-----1  ->    / \ / \   ->
  1127. X    /       \      / \   / \      2---3---4
  1128. X   /         \    /   \ /   \    / \ / \ / \
  1129. X  B-----------C  B-----2-----C  B---5---6---C
  1130. X
  1131. X    This algorithm is careful not to duplicate the (already existing)
  1132. X    vertices of the current triangles.  It should also not duplicate the
  1133. X    frequency edge vertices of adjacent faces.  Note that this algorithm
  1134. X    will work for ANY frequency, however frequencies beyond 5 would
  1135. X    require recompiling with a larger second dimension to the edge_point
  1136. X    array in FaceInfo, to hold more edge points.  Rotation sense of the
  1137. X    triangle's points is maintained (same as the original triangle).
  1138. X
  1139. XAdded on 8-24-91: Quadrilateral support!
  1140. X
  1141. X         freq = 1           freq = 2             freq = 3
  1142. X
  1143. X            A                    A                    A
  1144. X           / \                  / \                  / \
  1145. X          /   \                /   \                /   0
  1146. X         /     \              /     0              /     \
  1147. X        /       \            /     / \            2       1
  1148. X       /         \          /     /   \          /   3     \
  1149. X      /           D        1-    |     D        /           D
  1150. X     /            |       /  \-  /     |       /         4  |
  1151. X    /             |      /     \2---   |      6    7        5
  1152. X   /              |     /       |   \--3     /          8   |
  1153. X  /               |    /       /       |    /               9
  1154. X /                |   /       |        |   /                |
  1155. XB-----------------C  B--------4--------C  B---10---11---12--C
  1156. X
  1157. X
  1158. X    Quadrilaterals divide into the same number of sections as triangles, but
  1159. Xrequire more points to do so.  Quad support was added so that you can do
  1160. Xfrequency operations on cuboctahedrons, cubes, rhombic dodecahedrons, etc.
  1161. X
  1162. X*/
  1163. X
  1164. X
  1165. Xstruct FaceInfo {            /* info that each face needs to know */
  1166. X    uindex index[3];        /* concerning what faces are adjacent */
  1167. X    short kind[3];            /* which kind of shape is adjacent */
  1168. X    unsigned present : 3,    /* IF there is one */
  1169. X             direction : 3,    /* HOW: 0 is normal, 1 is reverse */
  1170. X             edge : 6;        /* WHICH edge of the adjacent face */
  1171. X    uindex edge_point[3][4];/* allows up to freq. 5: [3][f-1] */
  1172. X};
  1173. X
  1174. Xstruct QuadInfo {            /* info that each 4-sided poly needs to know */
  1175. X    uindex poly;            /* the index of the corresponding polygon */
  1176. X    uindex index[4];        /* concerning what faces are adjacent */
  1177. X    short kind[4];            /* which kind of shape is adjacent */
  1178. X    unsigned present : 4,    /* IF there is one */
  1179. X             direction : 4,    /* HOW: 0 is normal, 1 is reverse */
  1180. X             edge : 8;        /* WHICH edge of the adjacent face */
  1181. X    uindex edge_point[4][4];/* allows up to freq. 5: [4][f-1] */
  1182. X};
  1183. X
  1184. X/* values for the "kind" field in the above structures */
  1185. X#define K_FACE    1
  1186. X#define K_QUAD    2
  1187. X
  1188. X
  1189. Xvoid frequency()
  1190. X{
  1191. X    int id, freq, err, event;
  1192. X    int go = 1;
  1193. X    int quads, add_p, add_f, del_f, add_q, del_q;
  1194. X    index po0;
  1195. X
  1196. X    freq = 3;
  1197. X    sys_window(34, 2, "Tesselate Polyhedron");
  1198. X    sys_movecur(1,0);
  1199. X    sys_say_text("to Frequency (2..7):");
  1200. X    sys_get_long(freq, 1);
  1201. X    sys_activate(1);
  1202. X
  1203. X    while (go)
  1204. X    {
  1205. X        event = sys_read_event(&id, &freq);
  1206. X        switch (event)
  1207. X        {
  1208. X            case EV_CANCEL:
  1209. X                sys_close_window();
  1210. X                return;
  1211. X                break;
  1212. X            case EV_CHECKINT:
  1213. X            case EV_HITRETURN:
  1214. X                if (freq > 7) freq = 7;
  1215. X                if (freq < 2) freq = 2;
  1216. X                if (event == EV_HITRETURN) go = 0;
  1217. X                break;
  1218. X        }
  1219. X    }
  1220. X    sys_close_window();
  1221. X
  1222. X    /* Estimate how many actions the tesselation will require. */
  1223. X    /* Assume the worst case of all facets non-adjacent */
  1224. X    /* count how many quads we've got */
  1225. X    quads = 0;
  1226. X    for (po0 = 0; po0 < polys; po0++)
  1227. X        if (poly[po0].verts == 4) quads++;
  1228. X    add_p = faces * (fibo(freq + 1) - 3);    /* for the faces */
  1229. X    add_p += quads * ((freq * freq) - 4);    /* for the quads */
  1230. X    add_f = faces * freq * freq;
  1231. X    del_f = faces;
  1232. X    add_q = quads * freq * freq;
  1233. X    del_q = quads;
  1234. X
  1235. X    /* Make sure that this event won't overflow the undo buffer */
  1236. X    if (!enough_room(add_p, add_f, add_q, 0, del_f, del_q, 0, 4))
  1237. X    {
  1238. X        /* this operation will overflow the undo buffer! */
  1239. X        if (!tell_user_overflow()) return;
  1240. X    }
  1241. X
  1242. X    begin_operation();
  1243. X    err = bucky_frequency(freq);
  1244. X    end_operation();
  1245. X}
  1246. X
  1247. X
  1248. Xbucky_frequency(freq)
  1249. Xshort freq;
  1250. X{
  1251. X    index f, f2;        /* each face, signed for backwards loop */
  1252. X    index q, q2;        /* each quad, signed for backwards loop */
  1253. X    index fpoint[21];    /* allows frequencies of up to 5: (f+1)(f+2)/2 */
  1254. X    index fpoints;        /* temporary indices for current face triangle */
  1255. X    index qpoint[42];    /* allows frequencies of up to 5: (f+1)(f+2) */
  1256. X    index qpoints;        /* temporary indices for current quad */
  1257. X    index prev;            /* index of point at start of last row */
  1258. X    index row, i;        /* loops */
  1259. X    uindex p0, p1, p2, p3;
  1260. X    uindex e, e2;        /* edges */
  1261. X    Point3D vec[3],        /* 2 or 3 edge vectors, face or quad */
  1262. X           start,        /* coordinates of the start of each row */
  1263. X           end;            /* (for quads) coords of the end of each row */
  1264. X    uindex old_faces = faces;
  1265. X    uindex old_polys = polys;
  1266. X    struct FaceInfo *finfo = 0L, fcurrent;
  1267. X    struct QuadInfo *qinfo = 0L, qcurrent;
  1268. X    uindex adj_face, adj_quad, adj_edge, pos;
  1269. X    char add_the_point, flag;
  1270. X    index po0, po1;            /* polygon counter */
  1271. X    index quads;
  1272. X
  1273. X    /* count how many quads we've got */
  1274. X    quads = 0;
  1275. X    for (po0 = 0; po0 < polys; po0++)
  1276. X        if (poly[po0].verts == 4) quads++;
  1277. X
  1278. X    if (!faces && !quads) return OKAY;    /* must have SOMETHING to operate on */
  1279. X
  1280. X    if (freq < 2 || freq > 20) return OKAY;
  1281. X
  1282. X    /* we need to allocate memory, since the number of faces is variable */
  1283. X    if (faces)
  1284. X    {
  1285. X        if (flags.debug)
  1286. X            printf("allocating %d bytes for faces\n", faces*sizeof(struct FaceInfo));
  1287. X        finfo = (struct FaceInfo *)sys_alloc(faces*sizeof(struct FaceInfo));
  1288. X        if (!finfo)
  1289. X        {
  1290. X            screen_say("Not enough memory for that frequency");
  1291. X            return ERR_NOMEM;
  1292. X        }
  1293. X    }
  1294. X    if (quads)
  1295. X    {
  1296. X        if (flags.debug)
  1297. X            printf("allocating %d bytes for quads\n", quads*sizeof(struct QuadInfo));
  1298. X        qinfo = (struct QuadInfo *)sys_alloc(quads*sizeof(struct QuadInfo));
  1299. X        if (!qinfo)
  1300. X        {
  1301. X            screen_say("Not enough memory for that frequency");
  1302. X            return ERR_NOMEM;
  1303. X        }
  1304. X    }
  1305. X
  1306. X    /* we need to link our QuadInfo structures with real polygons */
  1307. X    quads = 0;
  1308. X    for (po0 = 0; po0 < polys; po0++)
  1309. X        if (poly[po0].verts == 4)
  1310. X            qinfo[quads++].poly = po0;
  1311. X
  1312. X    if (flags.debug) printf("frequency %d\n", freq);
  1313. X
  1314. X/*  Before triangulating, we scan all the faces and quads and assign each edge
  1315. X    a "master" face/quad that "owns" that edge.  Later, only this face/quad
  1316. X    will add vertice points along this edge.  The last face/quad will always
  1317. X    add    all it's edges.
  1318. X*/
  1319. X
  1320. X    for (f = 0; f < faces; f++)
  1321. X    {
  1322. X         finfo[f].present = 0;    /* by default, DO add the edge. */
  1323. X         finfo[f].direction = 0;
  1324. X         finfo[f].edge = 0;
  1325. X
  1326. X/**** Compare faces against faces */
  1327. X
  1328. X        for (f2 = f+1; f2 < faces; f2++)
  1329. X        {
  1330. X            for (e = 0; e < 3; e++)
  1331. X            {
  1332. X                p0 = face[f].p[e];
  1333. X                p1 = face[f].p[(e+1)%3];
  1334. X
  1335. X                for (e2 = 0; e2 < 3; e2++)
  1336. X                {
  1337. X                    /* There are two ways that one edge can match another:
  1338. X                        the point numbers can be identical or inverted.
  1339. X                        Edge i has indices i, (i+1)%3 for i = 0,1,2.
  1340. X                    */
  1341. X                    p2 = face[f2].p[e2];
  1342. X                    p3 = face[f2].p[(e2+1)%3];
  1343. X                    flag = 0;
  1344. X                    if (p0 == p2 && p1 == p3)
  1345. X                    {
  1346. X                        flag = 1;
  1347. X                    }
  1348. X                    else if (p0 == p3 && p1 == p2)
  1349. X                    {
  1350. X                        finfo[f].direction |= 1<<e;
  1351. X                        flag = 1;
  1352. X                    }
  1353. X                    if (flag)
  1354. X                    {
  1355. X                        finfo[f].present |= 1<<e;
  1356. X                        finfo[f].kind[e] = K_FACE;
  1357. X                        finfo[f].index[e] = f2;
  1358. X                        finfo[f].edge |= (e2 << (e << 1));
  1359. X                        break;
  1360. X                    }    
  1361. X                }
  1362. X            }
  1363. X        }
  1364. X
  1365. X/**** Compare faces against quads */
  1366. X
  1367. X        for (q2 = 0; q2 < quads; q2++)
  1368. X        {
  1369. X            po1 = qinfo[q2].poly;
  1370. X            for (e = 0; e < 3; e++)
  1371. X            {
  1372. X                p0 = face[f].p[e];
  1373. X                p1 = face[f].p[(e+1)%3];
  1374. X
  1375. X                for (e2 = 0; e2 < 4; e2++)
  1376. X                {
  1377. X                    p2 = poly[po1].p[e2];
  1378. X                    p3 = poly[po1].p[(e2+1)%4];
  1379. X                    flag = 0;
  1380. X                    if (p0 == p2 && p1 == p3)
  1381. X                    {
  1382. X                        flag = 1;
  1383. X                    }
  1384. X                    else if (p0 == p3 && p1 == p2)
  1385. X                    {
  1386. X                        finfo[f].direction |= 1<<e;
  1387. X                        flag = 1;
  1388. X                    }
  1389. X                    if (flag)
  1390. X                    {    
  1391. X                        finfo[f].present |= 1<<e;
  1392. X                        finfo[f].kind[e] = K_QUAD;
  1393. X                        finfo[f].index[e] = q2;
  1394. X                        finfo[f].edge |= (e2 << (e << 1));
  1395. X                        break;
  1396. X                    }
  1397. X                }
  1398. X            }
  1399. X        }
  1400. X    }
  1401. X
  1402. X/**** Compare quads against quads */
  1403. X
  1404. X    for (q = 0; q < quads-1; q++)
  1405. X    {
  1406. X        qinfo[q].present = 0;    /* by default, DO add the edge. */
  1407. X        qinfo[q].direction = 0;
  1408. X        qinfo[q].edge = 0;
  1409. X        po0 = qinfo[q].poly;
  1410. X
  1411. X        for (q2 = q+1; q2 < quads; q2++)
  1412. X        {
  1413. X            po1 = qinfo[q2].poly;
  1414. X            for (e = 0; e < 4; e++)
  1415. X            {
  1416. X                p0 = poly[po0].p[e];
  1417. X                p1 = poly[po0].p[(e+1)%4];
  1418. X
  1419. X                for (e2 = 0; e2 < 4; e2++)
  1420. X                {
  1421. X                    p2 = poly[po1].p[e2];
  1422. X                    p3 = poly[po1].p[(e2+1)%4];
  1423. X                    flag = 0;
  1424. X                    if (p0 == p2 && p1 == p3)
  1425. X                    {
  1426. X                        flag = 1;
  1427. X                    }
  1428. X                    else if (p0 == p3 && p1 == p2)
  1429. X                    {
  1430. X                        qinfo[q].direction |= 1<<e;
  1431. X                        flag = 1;
  1432. X                    }
  1433. X                    if (flag)
  1434. X                    {    
  1435. X                        qinfo[q].present |= 1<<e;
  1436. X                        qinfo[q].kind[e] = K_QUAD;
  1437. X                        qinfo[q].index[e] = q2;
  1438. X                        qinfo[q].edge |= (e2 << (e << 1));
  1439. X                        break;
  1440. X                    }    
  1441. X                }
  1442. X            }
  1443. X        }
  1444. X    }
  1445. X    /* the last quad is always MASTER! AH ha ha! */
  1446. X     if (quads) qinfo[quads-1].present = 0;
  1447. X
  1448. X/*********************************************/
  1449. X/** PHASE 2: the tesselation process itself. */
  1450. X/*********************************************/
  1451. X
  1452. X/*** Quads first! */
  1453. X
  1454. X    for (q = quads-1; q >= 0; q--)    /* count down through faces */
  1455. X    {
  1456. X        qpoints = 0;
  1457. X        po0 = qinfo[q].poly;
  1458. X        p0 = poly[po0].p[0];
  1459. X        p1 = poly[po0].p[1];
  1460. X        p2 = poly[po0].p[2];
  1461. X        p3 = poly[po0].p[3];
  1462. X        qcurrent = qinfo[q];
  1463. X
  1464. X        /* form the vectors A->B and D->C */
  1465. X        vec[0].x = point[p1].x - point[p0].x;
  1466. X        vec[0].y = point[p1].y - point[p0].y;
  1467. X        vec[0].z = point[p1].z - point[p0].z;
  1468. X        vec[1].x = point[p2].x - point[p3].x;
  1469. X        vec[1].y = point[p2].y - point[p3].y;
  1470. X        vec[1].z = point[p2].z - point[p3].z;
  1471. X
  1472. X        for (row = 0; row <= freq; row++)    /* there are frequency+1 rows */
  1473. X        {
  1474. X            /* prev is the index at the start of the previous row */
  1475. X            prev = (row * (row-1)) / 2;
  1476. X
  1477. X            start.x = point[p0].x + (row * vec[0].x / freq);
  1478. X            start.y = point[p0].y + (row * vec[0].y / freq);
  1479. X            start.z = point[p0].z + (row * vec[0].z / freq);
  1480. X
  1481. X            end.x = point[p3].x + (row * vec[1].x / freq);
  1482. X            end.y = point[p3].y + (row * vec[1].y / freq);
  1483. X            end.z = point[p3].z + (row * vec[1].z / freq);
  1484. X
  1485. X            vec[2].x = end.x - start.x;
  1486. X            vec[2].y = end.y - start.y;
  1487. X            vec[2].z = end.z - start.z;
  1488. X
  1489. X/** handle left edge */
  1490. X            /* the corners are special cases */
  1491. X            if (row == 0)
  1492. X                qpoint[qpoints++] = p0;    /* top */
  1493. X            else if (row == freq)
  1494. X                qpoint[qpoints++] = p1;    /* bottom left */
  1495. X            else
  1496. X            {
  1497. X                /* This is the first side (point 0 to point 1) */
  1498. X                if (qcurrent.present & 1)
  1499. X                {
  1500. X                    if (qcurrent.kind[0] == K_QUAD)
  1501. X                    {
  1502. X                        /* these edge points belong to another quad */
  1503. X                        adj_quad = qcurrent.index[0];
  1504. X                        adj_edge = (qcurrent.edge & 3);
  1505. X                        pos = (qcurrent.direction & 1 ? freq-row-1 : row-1);
  1506. X                        qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  1507. X                    }
  1508. X                    else sys_exit("fatal error 1");    /* should never occur! */
  1509. X                }
  1510. X                else
  1511. X                {
  1512. X                    /* these edge points belong to THIS face; create point */
  1513. X                    qpoint[qpoints++] = points;
  1514. X                    qinfo[q].edge_point[0][row-1] = points;
  1515. X                    add_point(start.x, start.y, start.z);
  1516. X                }
  1517. X            }
  1518. X
  1519. X/** move across, left to right */
  1520. X            for (i = 1; i <= freq; i++)
  1521. X            {
  1522. X                add_the_point = 0;
  1523. X
  1524. X                /* This point may be the bottom corner */
  1525. X                if (row == freq && i == freq) qpoint[qpoints++] = p2;
  1526. X
  1527. X                /* Or the upper right corner */
  1528. X                else if (row == 0 && i == freq) qpoint[qpoints++] = p3;
  1529. X
  1530. X                /* or it's the second side (point 1 to point 2) */
  1531. X                else if (row == freq && i != freq)
  1532. X                {
  1533. X                    if (qcurrent.present & 2)    /* the edge exists */
  1534. X                    {
  1535. X                        adj_quad = qcurrent.index[1];
  1536. X                        adj_edge = (qcurrent.edge >> 2) & 3;
  1537. X                        pos = (qcurrent.direction & 2 ? freq-i-1 : i-1);
  1538. X                        qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  1539. X                    }
  1540. X                    else    /* the edge must be created */
  1541. X                    {
  1542. X                        qinfo[q].edge_point[1][i-1] = points;
  1543. X                        add_the_point = 1;
  1544. X                    }
  1545. X                }
  1546. X
  1547. X                /* or it's the third side (point 2 to point 3) */
  1548. X                else if (row != 0 && row != freq && i == freq)
  1549. X                {
  1550. X                    if (qcurrent.present & 4)    /* the edge exists */
  1551. X                    {
  1552. X                        adj_quad = qcurrent.index[2];
  1553. X                        adj_edge = (qcurrent.edge >> 4) & 3;
  1554. X                        /* the following is backwards: subtle note below */
  1555. X                        pos = (qcurrent.direction & 4 ? row-1 : freq-row-1);
  1556. X                        qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  1557. X                    }
  1558. X                    else    /* the edge is created and specially numbered */
  1559. X                    {
  1560. X                        /* subtle point: we must be careful that the edge
  1561. X                            vertices are entered in the same clockwisdom
  1562. X                            as the vector point2->point0 */
  1563. X                        qinfo[q].edge_point[2][freq-row-1] = points;
  1564. X                        add_the_point = 1;
  1565. X                    }
  1566. X                }
  1567. X
  1568. X                /* or it's the fourth side (point 3 to point 0) */
  1569. X                else if (row == 0 && i != freq)
  1570. X                {
  1571. X                    if (qcurrent.present & 8)    /* the edge exists */
  1572. X                    {
  1573. X                        adj_quad = qcurrent.index[3];
  1574. X                        adj_edge = (qcurrent.edge >> 6) & 3;
  1575. X                        /* the following is backwards: subtle note below */
  1576. X                        pos = (qcurrent.direction & 8 ? i-1 : freq-i-1);
  1577. X                        qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  1578. X                    }
  1579. X                    else    /* the edge is created and specially numbered */
  1580. X                    {
  1581. X                        /* subtle point: we must be careful that the edge
  1582. X                            vertices are entered in the same clockwisdom
  1583. X                            as the vector point2->point0 */
  1584. X                        qinfo[q].edge_point[3][freq-i-1] = points;
  1585. X                        add_the_point = 1;
  1586. X                    }
  1587. X                }
  1588. X
  1589. X                /* otherwise, it's a point in the middle we need to create */
  1590. X                else add_the_point = 1;
  1591. X
  1592. X                if (add_the_point)
  1593. X                {
  1594. X                    qpoint[qpoints++] = points;
  1595. X                    add_point(start.x + (i * vec[2].x / freq),
  1596. X                              start.y + (i * vec[2].y / freq),
  1597. X                              start.z + (i * vec[2].z / freq));
  1598. X                }
  1599. X                if (row != 0)
  1600. X                {
  1601. X                    allocate_poly(4, colors.newface);
  1602. X                    poly[polys].p[0] = qpoint[(row-1)*(freq+1)+i-1];
  1603. X                    poly[polys].p[1] = qpoint[  row  *(freq+1)+i-1];
  1604. X                    poly[polys].p[2] = qpoint[  row  *(freq+1)+i  ];
  1605. X                    poly[polys].p[3] = qpoint[(row-1)*(freq+1)+i  ];
  1606. X                    finish_poly(0);
  1607. X                }
  1608. X            }
  1609. X        }
  1610. X    }
  1611. X
  1612. X/********* now do the faces */
  1613. X
  1614. X    for (f = faces-1; f >= 0; f--)    /* count down through faces */
  1615. X    {
  1616. X        fpoints = 0;
  1617. X        p0 = face[f].p[0];
  1618. X        p1 = face[f].p[1];
  1619. X        p2 = face[f].p[2];
  1620. X        fcurrent = finfo[f];
  1621. X
  1622. X        /* form the vectors A->B and B->C */
  1623. X        vec[0].x = point[p1].x - point[p0].x;
  1624. X        vec[0].y = point[p1].y - point[p0].y;
  1625. X        vec[0].z = point[p1].z - point[p0].z;
  1626. X        vec[1].x = point[p2].x - point[p1].x;
  1627. X        vec[1].y = point[p2].y - point[p1].y;
  1628. X        vec[1].z = point[p2].z - point[p1].z;
  1629. X
  1630. X        for (row = 0; row <= freq; row++)    /* there are frequency+1 rows */
  1631. X        {
  1632. X            /* prev is the index at the start of the previous row */
  1633. X            prev = (row * (row-1)) >> 1;
  1634. X
  1635. X            start.x = point[p0].x + (row * vec[0].x / freq);
  1636. X            start.y = point[p0].y + (row * vec[0].y / freq);
  1637. X            start.z = point[p0].z + (row * vec[0].z / freq);
  1638. X
  1639. X/** handle left edge */
  1640. X            /* the corners are special cases */
  1641. X            if (row == 0)
  1642. X                fpoint[fpoints++] = p0;    /* top */
  1643. X            else if (row == freq)
  1644. X                fpoint[fpoints++] = p1;    /* bottom left */
  1645. X            else
  1646. X            {
  1647. X                /* This is the first side (point 0 to point 1) */
  1648. X                if (fcurrent.present & 1)
  1649. X                {
  1650. X                    if (fcurrent.kind[0] == K_FACE)
  1651. X                    {
  1652. X                        /* these edge points belong to another face */
  1653. X                        adj_face = fcurrent.index[0];
  1654. X                        adj_edge = (fcurrent.edge & 3);
  1655. X                        pos = (fcurrent.direction & 1 ? freq-row-1 : row-1);
  1656. X                        fpoint[fpoints++] = finfo[adj_face].edge_point[adj_edge][pos];
  1657. X                    }
  1658. X                    else if (fcurrent.kind[0] == K_QUAD)
  1659. X                    {
  1660. X                        /* these edge points belong to another face */
  1661. X                        adj_quad = fcurrent.index[0];
  1662. X                        adj_edge = (fcurrent.edge & 3);
  1663. X                        pos = (fcurrent.direction & 1 ? freq-row-1 : row-1);
  1664. X                        fpoint[fpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  1665. X                    }
  1666. X                    else sys_exit("fatal error 2");    /* should never occur! */
  1667. X                }
  1668. X                else
  1669. X                {
  1670. X                    /* these edge points belong to THIS face; create point */
  1671. X                    fpoint[fpoints++] = points;
  1672. X                    finfo[f].edge_point[0][row-1] = points;
  1673. X                    add_point(start.x, start.y, start.z);
  1674. X                }
  1675. X            }
  1676. X
  1677. X/** move across, left to right */
  1678. X            for (i = 0; i < row; i++)
  1679. X            {
  1680. X                add_the_point = 0;
  1681. X
  1682. X                /* This point may be the bottom corner */
  1683. X                if (row == freq && i == row-1) fpoint[fpoints++] = p2;
  1684. X
  1685. X                /* or it's the second side (point 1 to point 2) */
  1686. X                else if (row == freq && i != row-1)
  1687. X                {
  1688. X                    if (fcurrent.present & 2)    /* the edge exists */
  1689. X                    {
  1690. X                        if (fcurrent.kind[1] == K_FACE)
  1691. X                        {
  1692. X                            adj_face = fcurrent.index[1];
  1693. X                            adj_edge = (fcurrent.edge >> 2) & 3;
  1694. X                            pos = (fcurrent.direction & 2 ? freq-2-i : i);
  1695. X                            fpoint[fpoints++] = finfo[adj_face].edge_point[adj_edge][pos];
  1696. X                        }
  1697. X                        else if (fcurrent.kind[1] == K_QUAD)
  1698. X                        {
  1699. X                            adj_quad = fcurrent.index[1];
  1700. X                            adj_edge = (fcurrent.edge >> 2) & 3;
  1701. X                            pos = (fcurrent.direction & 2 ? freq-2-i : i);
  1702. X                            fpoint[fpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  1703. X                        }
  1704. X                        else sys_exit("fatal error 3");    /* should never occur! */
  1705. X                    }
  1706. X                    else    /* the edge must be created */
  1707. X                    {
  1708. X                        finfo[f].edge_point[1][i] = points;
  1709. X                        add_the_point = 1;
  1710. X                    }
  1711. X                }
  1712. X
  1713. X                /* or it's the third side (point 2 to point 0) */
  1714. X                else if (row != freq && i == row-1)
  1715. X                {
  1716. X                    if (fcurrent.present & 4)    /* the edge exists */
  1717. X                    {
  1718. X                        if (fcurrent.kind[2] == K_FACE)
  1719. X                        {
  1720. X                            adj_face = fcurrent.index[2];
  1721. X                            adj_edge = (fcurrent.edge >> 4) & 3;
  1722. X                            /* the following is backwards: subtle note below */
  1723. X                            pos = (fcurrent.direction & 4 ? row-1 : freq-row-1);
  1724. X                            fpoint[fpoints++] = finfo[adj_face].edge_point[adj_edge][pos];
  1725. X                        }
  1726. X                        else if (fcurrent.kind[2] == K_QUAD)
  1727. X                        {
  1728. X                            adj_quad = fcurrent.index[2];
  1729. X                            adj_edge = (fcurrent.edge >> 4) & 3;
  1730. X                            /* the following is backwards: subtle note below */
  1731. X                            pos = (fcurrent.direction & 4 ? row-1 : freq-row-1);
  1732. X                            fpoint[fpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  1733. X                        }
  1734. X                        else sys_exit("fatal error 4");    /* should never occur! */
  1735. X                    }
  1736. X                    else    /* the edge is created and specially numbered */
  1737. X                    {
  1738. X                        /* subtle point: we must be careful that the edge
  1739. X                            vertices are entered in the same clockwisdom
  1740. X                            as the vector point2->point0 */
  1741. X                        finfo[f].edge_point[2][freq-row-1] = points;
  1742. X                        add_the_point = 1;
  1743. X                    }
  1744. X                }
  1745. X                /* otherwise, it's a point in the middle we need to create */
  1746. X                else add_the_point = 1;
  1747. X
  1748. X                if (add_the_point)
  1749. X                {
  1750. X                    fpoint[fpoints++] = points;
  1751. X                    add_point(start.x + ((i+1) * vec[1].x / freq),
  1752. X                              start.y + ((i+1) * vec[1].y / freq),
  1753. X                              start.z + ((i+1) * vec[1].z / freq));
  1754. X                }
  1755. X                if (i > 0) add_face(fpoint[prev + i - 1],
  1756. X                                    fpoint[fpoints - 2],
  1757. X                                    fpoint[prev + i], colors.newface, 0);
  1758. X                add_face(fpoint[prev + i],
  1759. X                         fpoint[fpoints - 2],
  1760. X                         fpoint[fpoints - 1], colors.newface, 0);
  1761. X            }
  1762. X        }
  1763. X    }
  1764. X
  1765. X    /* remove the old faces */
  1766. X    for (f = 0; f < old_faces; f++) delete_face(f, 0);
  1767. X
  1768. X    /* remove the old polys */
  1769. X    for (q = 0; q < old_polys; q++)
  1770. X        if (poly[q].verts == 4) delete_poly(q, 0);
  1771. X
  1772. X    /* free our temporary memory */
  1773. X    if (finfo) sys_free(finfo, sizeof(struct FaceInfo)*old_faces);
  1774. X    if (qinfo) sys_free(qinfo, sizeof(struct QuadInfo)*quads);
  1775. X
  1776. X    convert_points();
  1777. X    return OKAY;
  1778. X}
  1779. X
  1780. X
  1781. END_OF_FILE
  1782. if test 19873 -ne `wc -c <'freq.c'`; then
  1783.     echo shar: \"'freq.c'\" unpacked with wrong size!
  1784. fi
  1785. # end of 'freq.c'
  1786. fi
  1787. echo shar: End of archive 3 \(of 6\).
  1788. cp /dev/null ark3isdone
  1789. MISSING=""
  1790. for I in 1 2 3 4 5 6 ; do
  1791.     if test ! -f ark${I}isdone ; then
  1792.     MISSING="${MISSING} ${I}"
  1793.     fi
  1794. done
  1795. if test "${MISSING}" = "" ; then
  1796.     echo You have unpacked all 6 archives.
  1797.     rm -f ark[1-9]isdone
  1798. else
  1799.     echo You still need to unpack the following archives:
  1800.     echo "        " ${MISSING}
  1801. fi
  1802. ##  End of shell archive.
  1803. exit 0
  1804. -- 
  1805. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  1806. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  1807. Post requests for sources, and general discussion to comp.sys.amiga.misc.
  1808.